#ifndef NETLIB_STRINGPIECE_H
#define NETLIB_STRINGPIECE_H

// 用于高效的字符串传递，减少内存拷贝

#include <string.h>
#include <iosfwd>

#include "Types.h"

namespace netlib
{

class StringArg // 暂未使用，简单的字符串类
{
public:
    StringArg(const char* str): str_(str)
    { }

    StringArg(const string& str) : str_(str.c_str())
    { }

    const char* c_str() const { return str_; }

private:
    const char* str_;
    
}; // class StringArg end

class StringPiece 
{
private:
    const char*   ptr_;         // 指向字符串
    int           length_;      // 字符串长度

public:

    StringPiece() : ptr_(NULL), length_(0) // 空参构造
    { }

    // 传一个char*,直接赋给ptr_并统计长度
    StringPiece(const char* str) : ptr_(str), length_(static_cast<int>(strlen(ptr_)))
    { }

    // 传一个unsigned char*,直接赋给ptr_并统计长度
    StringPiece(const unsigned char* str)
        : ptr_(reinterpret_cast<const char*>(str)),
        length_(static_cast<int>(strlen(ptr_)))
    { }

    // 传一个string,在参数列表中调用.data()得到底层char*，赋给ptr_并统计长度
    StringPiece(const string& str)
         : ptr_(str.data()),
        length_(static_cast<int>(str.size()))
    { }

    // 传一个char*,直接赋给ptr_并统计长度len
    StringPiece(const char* offset, int len)
        : ptr_(offset),
        length_(len)
    { }

    const char* data() const { return ptr_; } // 返回char*指针

    int size() const { return length_; } // 返回字符串长度

    bool empty() const { return length_ == 0; } // 判断是否为空字符串
    
    const char* begin() const { return ptr_; } // 返回字符串开头

    const char* end() const { return ptr_ + length_; } // 返回字符串结尾

    void clear() { ptr_ = NULL; length_ = 0; } // 字符指针置空，长度清零

    // 重新设置字符串和长度
    void set(const char* buffer, int len) { ptr_ = buffer; length_ = len; }

    void set(const char* str) // 重新设置字符串，长度自动获取
    {
        ptr_ = str;
        length_ = static_cast<int>(strlen(str));
    }

    void set(const void* buffer, int len) // 传入一个地址和长度，尝试转换成字符串并赋值长度
    {
        ptr_ = reinterpret_cast<const char*>(buffer);
        length_ = len;
    }

    char operator[](int i) const { return ptr_[i]; } // 重载[]

    void remove_prefix(int n) // 从字符串头部起移除n个字符
    {
        ptr_ += n;
        length_ -= n;
    }

    void remove_suffix(int n) { length_ -= n; } // 字符串长度减少n

    bool operator==(const StringPiece& x) const
    {
        return ((length_ == x.length_) &&
                (memcmp(ptr_, x.ptr_, length_) == 0));
    }

    bool operator!=(const StringPiece& x) const
    {
        return !(*this == x);
    }

#define STRINGPIECE_BINARY_PREDICATE(cmp,auxcmp)                             \
    bool operator cmp (const StringPiece& x) const {                           \
        int r = memcmp(ptr_, x.ptr_, length_ < x.length_ ? length_ : x.length_); \
        return ((r auxcmp 0) || ((r == 0) && (length_ cmp x.length_)));          \
    }
    STRINGPIECE_BINARY_PREDICATE(<,  <);
    STRINGPIECE_BINARY_PREDICATE(<=, <);
    STRINGPIECE_BINARY_PREDICATE(>=, >);
    STRINGPIECE_BINARY_PREDICATE(>,  >);
#undef STRINGPIECE_BINARY_PREDICATE

    int compare(const StringPiece& x) const // 比较两个字符串是否相等
    {
        int r = memcmp(ptr_, x.ptr_, length_ < x.length_ ? length_ : x.length_);
        if (r == 0)
        {
            if (length_ < x.length_) // 因为memcmp的比较机制，需要考虑两个字符串的长度
                r = -1;
            else if (length_ > x.length_)
                r = +1;
        }
        return r;
    }

    string as_string() const { return string(data(), size()); } // 转换成string对象

    // 将当前对象复制给参数string对象
    void CopyToString(string* target) const { target->assign(ptr_, length_); }

    // 比较两个StringPiece对象是否相等
    bool starts_with(const StringPiece& x) const
    { return ((length_ >= x.length_) && (memcmp(ptr_, x.ptr_, x.length_) == 0)); }

}; // class StringPiece end

} // namespace netlib end

#ifdef HAVE_TYPE_TRAITS
// This makes vector<StringPiece> really fast for some STL implementations
template<> struct __type_traits<netlib::StringPiece> {
  typedef __true_type    has_trivial_default_constructor;
  typedef __true_type    has_trivial_copy_constructor;
  typedef __true_type    has_trivial_assignment_operator;
  typedef __true_type    has_trivial_destructor;
  typedef __true_type    is_POD_type;
};
#endif

// allow StringPiece to be logged
std::ostream& operator<<(std::ostream& o, const netlib::StringPiece& piece);

#endif